package com.imoocdl.service.impl;

import com.imoocdl.converter.OrderMaster2OrderDTOConverter;
import com.imoocdl.dataobject.OrderDetail;
import com.imoocdl.dataobject.OrderMaster;
import com.imoocdl.dataobject.ProductInfo;
import com.imoocdl.dto.CartDTO;
import com.imoocdl.dto.OrderDtDTO;
import com.imoocdl.enums.OrderStatusEnum;
import com.imoocdl.enums.PayStatusEnum;
import com.imoocdl.enums.ResultEnum;
import com.imoocdl.exception.SellException;
import com.imoocdl.repository.OrderDetailRepository;
import com.imoocdl.repository.OrderMasterRepository;
import com.imoocdl.service.*;
import com.imoocdl.utils.KeyUtil;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by pc on 2018/3/31.
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {


    @Autowired
    private OrderMasterRepository orderMasterRepository;

    @Autowired
    private ProductService productService;

    @Autowired
    private OrderDetailRepository orderDetailRepository;

    @Autowired
    private PayService payService;

    @Autowired
    private PushMessage pushMessage;
    @Autowired
    private WebSocket webSocket;


    @Override
    @Transactional
    public OrderDtDTO create(OrderDtDTO orderDtDTO) {
        //1,计算商品的(数量,价格)
        String orderId = KeyUtil.genUniqueKey();
        BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);
        for(OrderDetail orderDetail:orderDtDTO.getOrderDetailList()){
            ProductInfo productInfo =productService.findOne(orderDetail.getProductId());
            if(productInfo == null){
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }
            //计算订单总价
            orderAmount =   productInfo.getProductPrice().multiply(new BigDecimal(orderDetail.getProductQuantity())).add(orderAmount);
            //订单详情入库
            BeanUtils.copyProperties(productInfo,orderDetail);
            orderDetail.setDetailId(KeyUtil.genUniqueKey());
            orderDetail.setOrderId(orderId);
            orderDetailRepository.save(orderDetail);
        }

        //写入订单数据库

        OrderMaster orderMaster = new OrderMaster();
        orderDtDTO.setOrderId(orderId);
        orderDtDTO.setOrderAmount(orderAmount);
        orderDtDTO.setOrderStatus(OrderStatusEnum.NEW.getCode());
        orderDtDTO.setPayStatus(PayStatusEnum.WAIT.getCode());
        BeanUtils.copyProperties(orderDtDTO,orderMaster);
        orderMasterRepository.save(orderMaster);

        //扣库存
        List<CartDTO> cartDTOList =  orderDtDTO.getOrderDetailList().stream().
                map(e -> new CartDTO(e.getProductId(),e.getProductQuantity()))
                .collect(Collectors.toList());
        productService.decreaseStock(cartDTOList);
      //发送webSocket 消息给前端
        webSocket.sendMessage("有新的订单,id:"+orderDtDTO.getOrderId());
        return orderDtDTO;
    }

    @Override
    public OrderDtDTO findOne(String orderId) {
        OrderMaster orderMaster = orderMasterRepository.findOne(orderId);
        if(orderMaster == null){
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }
        List<OrderDetail> orderDetailList = orderDetailRepository.findByOrderId(orderId);
        if(CollectionUtils.isEmpty(orderDetailList)){
            throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST);
        }
        OrderDtDTO orderDtDTO = new OrderDtDTO();
        BeanUtils.copyProperties(orderMaster,orderDtDTO);
        orderDtDTO.setOrderDetailList(orderDetailList);
        return orderDtDTO;
    }

    /**
     * 分页查询订单列表
     * @param buyerOpenid
     * @param pageable
     * @return
     */
    @Override
    public Page<OrderDtDTO> findList(String buyerOpenid, Pageable pageable) {
    Page<OrderMaster> list =   orderMasterRepository.findByBuyerOpenid(buyerOpenid,pageable);
      List<OrderDtDTO> orderDtDTOList =  OrderMaster2OrderDTOConverter.convert(list.getContent());
      Page<OrderDtDTO> orderDtDTOPage = new PageImpl<OrderDtDTO>(orderDtDTOList,pageable,list.getTotalElements());
        return orderDtDTOPage;
    }

    @Override
    @Transactional
    public OrderDtDTO cancel(OrderDtDTO orderDtDTO) {
        OrderMaster orderMaster = new OrderMaster();

        //判断订单状态
        if(!orderDtDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.error("取消订单状态不正确"+orderDtDTO.getOrderId()+"的订单状态为:"+orderDtDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //修改订单状态
        orderDtDTO.setOrderStatus(OrderStatusEnum.CANCEL.getCode());
        BeanUtils.copyProperties(orderDtDTO,orderMaster);
           OrderMaster om =  orderMasterRepository.save(orderMaster);
           if(om == null){
               log.error("取消订单 更新失败  orderMaster={}",orderMaster);
               throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
           }
        //返还库存
        if(CollectionUtils.isEmpty(orderDtDTO.getOrderDetailList())){
               log.error("取消订单 订单中无商品详情 orderDtDTO={}",orderDtDTO);
               throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY);
        }
      List<CartDTO> cartDTOList =  orderDtDTO.getOrderDetailList().stream().map(e -> new CartDTO(e.getProductId(),e.getProductQuantity()) ).collect(Collectors.toList());
       productService.increaseStock(cartDTOList);
        //如果以支付 ,需要退款
        if(orderDtDTO.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())){
            payService.refund(orderDtDTO);
        }
        return orderDtDTO;
    }

    @Override
    @Transactional
    public OrderDtDTO finish(OrderDtDTO orderDtDTO) {
        //判断订单状态
        if(!orderDtDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.info("完结订单 订单状态不正确"+orderDtDTO.getOrderId()+"的订单状态为:"+orderDtDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        orderDtDTO.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderDtDTO,orderMaster);
       OrderMaster result =  orderMasterRepository.save(orderMaster);
       if(result == null){
           log.info("完结订单 更新失败"+orderMaster.toString());
           throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
       }
        //推送微信的模板消息
        pushMessage.orderStatus(orderDtDTO);
        return orderDtDTO;
    }

    @Override
    @Transactional
    public OrderDtDTO paid(OrderDtDTO orderDtDTO) {
        //判断订单状态
        if(!orderDtDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.info("订单支付成功 订单状态不正确"+orderDtDTO.getOrderId()+"的订单状态为:"+orderDtDTO.getOrderStatus());
            throw new SellException(ResultEnum.ORDER_STATUS_ERROR);
        }
        //判断支付状态
        if(!orderDtDTO.getPayStatus().equals(PayStatusEnum.WAIT.getCode())){
            log.info(" 该订单已经支付"+orderDtDTO.toString());
            throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR);
        }
        //修改支付状态
        orderDtDTO.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        OrderMaster orderMaster = new OrderMaster();
        BeanUtils.copyProperties(orderDtDTO,orderMaster);
      OrderMaster result =   orderMasterRepository.save(orderMaster);
      if(result == null){
          log.info("订单支付完成 更新失败"+orderDtDTO.toString());
          throw new SellException(ResultEnum.ORDER_UPDATE_FAIL);
      }
        return orderDtDTO;
    }

    @Override
    public Page<OrderDtDTO> findList(Pageable pageable) {
        Page<OrderMaster> list =   orderMasterRepository.findAll(pageable);
        List<OrderDtDTO> orderDtDTOList =  OrderMaster2OrderDTOConverter.convert(list.getContent());
        Page<OrderDtDTO> orderDtDTOPage = new PageImpl<OrderDtDTO>(orderDtDTOList,pageable,list.getTotalElements());
        return orderDtDTOPage;
    }
}
